;;==========================================================================
;; Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
;;==========================================================================

    INCLUDE kxarm.h



    AREA |.text|,ALIGN=2,CODE,READONLY

DEBUGINTERLOCK  EQU     0

INVALIDREF  EQU 0xBADBADBA

;==========================================================================
;Int32 InterlockedIncrement(PInt32 pAddend)

    EXPORT InterlockedIncrement
InterlockedIncrement
    ldr r2, =INVALIDREF
    swp r1, r2, [r0]   ;(r0)-->r1, r2->(r0)
    cmp r1, r2

    IF DEBUGINTERLOCK
    beq PUTCHAR1
    ELSE
    beq InterlockedIncrement
    ENDIF

    add r1, r1, #1
    str r1, [r0]
    mov r0, r1
    mov pc, lr

    IF DEBUGINTERLOCK
PUTCHAR1
    IMPORT DBG_SendChar
    stmdb sp!, {r0,lr}
    mov r0, #0x41
    bl DBG_SendChar
    ldmia sp!, {r0,lr}
    b InterlockedIncrement
    ENDIF
;==========================================================================
;Int32 InterlockedDecrement(PInt32 pAddend)

    EXPORT InterlockedDecrement
InterlockedDecrement
    ldr r2, =INVALIDREF
    swp r1, r2, [r0]    ;(r0)-->r1, r2->(r0)
    cmp r1, r2

    IF DEBUGINTERLOCK
    beq PUTCHAR2
    ELSE
    beq InterlockedDecrement
    ENDIF

    add r1, r1, #-1
    str r1, [r0]
    mov r0, r1
    mov pc, lr

    IF DEBUGINTERLOCK
PUTCHAR2
    stmdb sp!, {r0,lr}
    mov r0, #0x42
    bl DBG_SendChar
    ldmia sp!, {r0,lr}
    b InterlockedDecrement
    ENDIF
;==========================================================================
;Int32 InterlockedExchangeAdd(PInt32 pAddend, Int32 Increment)

    EXPORT InterlockedExchangeAdd
InterlockedExchangeAdd
    ldr r2, =INVALIDREF
    swp r3, r2, [r0]  ;(r0)-->r3 , r2-->(r0)
    cmp r3, r2

    IF DEBUGINTERLOCK
    beq PUTCHAR3
    ELSE
    beq InterlockedExchangeAdd
    ENDIF

    add r3, r3, r1
    str r3, [r0]
    mov r0, r3
    mov pc, lr

    IF DEBUGINTERLOCK
PUTCHAR3
    stmdb sp!, {r0,r1,lr}
    mov r0, #0x43
    bl DBG_SendChar
    ldmia sp!, {r0,r1,lr}
    b InterlockedExchangeAdd
    ENDIF
;==========================================================================
;Int32 InterlockedExchange(PInt32 Target, Int32 Value)

    EXPORT InterlockedExchange
InterlockedExchange
    swp r1, r1, [r0]
    mov r0, r1
    mov pc, lr

;==========================================================================
;EXTERN_C Int32 InterlockedCompareExchange(
;              PInt32 destination, Int32 exchange, Int32 comperand)
    EXPORT InterlockedCompareExchange
InterlockedCompareExchange
    mov r3, r0            ; 1st addr to r3
    ldr r12, =INVALIDREF
CompareExchangeLoop
    swp r0, r12, [r3]      ; swp old value to r0
    cmp r12, r0

    IF DEBUGINTERLOCK
    beq PUTCHAR4
    ELSE
    beq CompareExchangeLoop
    ENDIF

    cmp r2, r0            ;compare old value and comperand
    streq r1, [r3]          ; exchange---> destination
    strne r0, [r3]          ; restore the frist arg

    mov pc, lr

    IF DEBUGINTERLOCK
PUTCHAR4
    stmdb sp!, {r0,r1,lr}
    mov r0, #0x44
    bl DBG_SendChar
    ldmia sp!, {r0,r1,lr}
    b CompareExchangeLoop
    ENDIF

;==========================================================================
; disable fiq and irq, return r0 include the cpsr content

    EXPORT save_flags_cli
save_flags_cli
    mrs     r0, cpsr    ; return current flags for restore later
    orr     r12, r0, #0xC0  ;cli
    msr     cpsr_cf, r12

    mov     pc, lr

;==========================================================================
; r0 include the cpsr content

    EXPORT  restore_flags
restore_flags
    msr     cpsr_cf, r0
    mov     pc, lr

;==========================================================================
;
; Cli()
; Disable the maskable processor interrupts.
; Disable irq and fiq interrupts.
; zero---enable, one---disable.
    EXPORT Cli
Cli
    mrs     r0, cpsr
    orr     r0, r0, #0xC0
    msr     cpsr_cf, r0
    mov     pc, lr

;==========================================================================
; Sti()
; Enable maskable interrupts
; Enable irq and fiq interrupts.
; if should we enable or disable irq and fiq respectively
    EXPORT Sti
Sti
    mrs     r0, cpsr
    bic     r0, r0, #0xC0
    msr     cpsr_cf, r0
    mov     pc, lr

;==========================================================================
;BOOL InterruptsDisabled(void)
;check if interrupts disabled ?
;    EXPORT InterruptsDisabled
InterruptsDisabled
    mrs     r0, cpsr
    and     r0, r0, #0x80
    mov     pc, lr

;==========================================================================
    EXPORT  GetCpsr
GetCpsr
    mrs     r0, cpsr
    mov     pc, lr

;==========================================================================
;Address GetSP(void);
;get current stack pointer
    EXPORT  GetSP
GetSP
    mov     r0, sp
    mov     pc, lr
;end of GetSP
;==========================================================================
;

;---------------------------------------------------
;EXTERN_C void sys_cmpxchg(PInt32, Int32, Int32);
    EXPORT sys_cmpxchg
sys_cmpxchg
    mrs		r3,cpsr
	tst	    r3,#0x0f
	bne     knl_codex

    swi 21  ;syscall_comxchg
    mov pc, lr   ;return
knl_codex

    MRS     r3, cpsr    ;save cpsr in r3
    orr     r12, r3, #0xc0
    MSR     cpsr_cf, r12
  	ldr     r12, [r0]
  	cmp     r12, r2
    swpeq   r1, r1, [r0]
    moveq   r0, r1      ;if swap, return old value
    movne   r0, r12     ;if not swap, return old value too
    MSR     cpsr_cf, r3 ;restor cpsr
	mov     pc, lr
;---------------------------------------------------


    ALIGN

    END
